package com.evil.application.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.application.mapper.FormControlOptionMapper;
import com.evil.application.pojo.bo.application.form.control.option.FormControlOptionBO;
import com.evil.application.pojo.dto.form.control.option.FormOptionRespDTO;
import com.evil.application.pojo.dto.form.control.save.CopyControlDTO;
import com.evil.application.pojo.dto.form.control.save.SaveControlRespDTO;
import com.evil.application.pojo.entity.FormControlOption;
import com.evil.application.service.FormControlOptionService;
import com.evil.common.core.enums.SpecialFieldEnum;
import com.evil.common.core.util.StreamUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 表单控件下拉选项表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@RestController
@AllArgsConstructor
public class FormControlOptionServiceImpl extends ServiceImpl<FormControlOptionMapper, FormControlOption> implements FormControlOptionService {

    private final ApplicationLogServiceImpl logService;

    /**
     * 获取选项
     *
     * @param id id
     * @return FormOptionRespDTO
     */
    @Override
    public FormOptionRespDTO findBaseById(Long id) {
        return null;
    }

    /**
     * 获取选项列表
     *
     * @param ids           ids
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    @Override
    public List<FormOptionRespDTO> findBaseByIds(Collection<Long> ids, boolean filterDeleted) {
        return null;
    }

    /**
     * 获取选项列表
     *
     * @param ids           ids
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    @Override
    public Map<Long, FormOptionRespDTO> findBaseMapByIds(Collection<Long> ids, boolean filterDeleted) {
        return null;
    }

    /**
     * 获取控件选项列表
     *
     * @param controlId     controlId
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    @Override
    public List<FormOptionRespDTO> findBaseByControlId(Long controlId, boolean filterDeleted) {
        return StreamUtil.transListT(this.baseMapper.findByControlId(controlId, filterDeleted), FormOptionRespDTO::new);
    }

    /**
     * 获取控件选项列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    @Override
    public List<FormOptionRespDTO> findBaseByControlIds(Collection<Long> controlIds, boolean filterDeleted) {
        return null;
    }

    /**
     * 获取控件选项列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    @Override
    public Map<Long, List<FormOptionRespDTO>> findBasesByControlIds(Collection<Long> controlIds, boolean filterDeleted) {
        return null;
    }

    /**
     * 获取控件选项列表
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return FormOptionRespDTO 列表
     */
    @Override
    public Map<Long, Map<Long, FormOptionRespDTO>> findBaseMapByControlIds(Collection<Long> controlIds, boolean filterDeleted) {
        return null;
    }

    /**
     * 递归保存控件选择项
     *
     * @param controlId          controlId
     * @param options            options
     * @param parentOptionId     parentOptionId
     * @param saveControlRespDTO optionsAndControlIdMapDTO
     */
    @Override
    public void recursionSaveOptions(Long controlId, Long parentOptionId, Map<Long, FormControlOption> optionMap, List<FormOptionRespDTO> options, SaveControlRespDTO saveControlRespDTO) {
        if (CollectionUtil.isEmpty(options)) {
            return;
        }
        AtomicInteger sort = new AtomicInteger();
        options.forEach(optionRespDTO -> {
            Long optionId;
            FormControlOption formControlOption;
            if (null != optionRespDTO.getOptionId() && optionMap.containsKey(optionRespDTO.getOptionId())) {
                formControlOption = optionMap.get(optionRespDTO.getOptionId());
                optionId = formControlOption.getOptionId();
            } else {
                formControlOption = new FormControlOption();
                optionId = null;
            }
            BeanUtil.copyProperties(optionRespDTO, formControlOption);
            formControlOption.setOptionId(optionId);
            formControlOption.setControlId(controlId);
            formControlOption.setParentOptionId(parentOptionId);
            formControlOption.setSort(sort.getAndIncrement());

            // 下拉项联动控件
            formControlOption.setLinkControlIds(JSON.toJSONString(optionRespDTO.getLinkControlIds()));

            logService.saveAndCheck(this.baseMapper, FormControlOption::getOptionId, formControlOption);
            // 记录控件 新旧映射选项id
            saveControlRespDTO.putControlOptionId(controlId, optionRespDTO.getOptionId(), formControlOption.getOptionId());

            // 有联动控件则需要记录当前选项，递归结束后统一处理联动控件ID
            if (!optionRespDTO.getLinkControlIds().isEmpty()) {
                saveControlRespDTO.getOptionList().add(formControlOption);
            }

            // 递归
            this.recursionSaveOptions(controlId, formControlOption.getOptionId(), optionMap, optionRespDTO.getChildrenOptions(), saveControlRespDTO);
        });
    }

    /**
     * 递归复制控件选项
     *
     * @param controlId             controlId
     * @param parentOptionId        父级选项
     * @param sourceOptions         当前层级选项
     * @param targetSourceOptionMap 目标源选项
     * @param copyControlDTO        复制参数
     * @param updateSource          是否更新源信息
     */
    @Override
    public void recursionCopyOptions(Long controlId,
                                     Long parentOptionId,
                                     List<FormControlOptionBO> sourceOptions,
                                     Map<Long, FormControlOption> targetSourceOptionMap,
                                     CopyControlDTO copyControlDTO,
                                     boolean updateSource) {
        AtomicInteger sort = new AtomicInteger();
        sourceOptions.forEach(option -> {
            FormControlOption copyOption;
            Long optionId;
            if (targetSourceOptionMap.containsKey(option.getOptionId())) {
                copyOption = targetSourceOptionMap.get(option.getOptionId());
                optionId = copyOption.getOptionId();
            } else {
                optionId = null;
                copyOption = new FormControlOption();
            }
            BeanUtil.copyProperties(option, copyOption, SpecialFieldEnum.getSpecialFields());
            copyOption.setOptionId(optionId);
            copyOption.setControlId(controlId);
            copyOption.setParentOptionId(parentOptionId);
            copyOption.setSourceOptionId(option.getOptionId());
            copyOption.setSort(sort.getAndIncrement());

            logService.saveAndCheck(this.baseMapper, FormControlOption::getOptionId, copyOption);

            // 记录选项id
            copyControlDTO.putControlOptionId(controlId, option.getOptionId(), copyOption.getOptionId());
            // 记录选项
            if (StringUtils.isNotBlank(copyOption.getLinkControlIds())) {
                copyControlDTO.getOptionList().add(copyOption);
            }

            // 更新源映射信息
            if (updateSource && !option.getSourceOptionId().equals(copyOption.getOptionId())) {
                option.setSourceOptionId(copyOption.getOptionId());
                FormControlOption formControlOption = BeanUtil.copyProperties(option, FormControlOption.class);
                logService.saveAndCheck(this.baseMapper, FormControlOption::getOptionId, formControlOption);
            }

            // 递归保存
            this.recursionCopyOptions(controlId, copyOption.getOptionId(), option.getChild(), targetSourceOptionMap, copyControlDTO, updateSource);
        });
    }
}
